﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.IO;
using System.Xml;
using System.Diagnostics;
using Engine.Sgml;
using System.Xml.XPath;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Engine.Dtd.Schema;

namespace Engine.Sgml.Test {
    /// <summary>
    /// Summary description for SgmlReaderTester
    /// </summary>
    [TestClass]
    public class SgmlDocumentTest {
        public SgmlDocumentTest() {
            //
            // TODO: Add constructor logic here
            //
            }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext {
            get {
                return testContextInstance;
                }
            set {
                testContextInstance = value;
                }
            }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext) {

        //    }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        [TestInitialize()]
        public void MyTestInitialize() {
            DirectoryInfo fileDirectory = Directory.GetParent(TestContext.TestDir).Parent;

            DirectoryInfo schemaDirectory = new DirectoryInfo(Path.Combine(fileDirectory.FullName, @"Engine.Sgml.Test\Scheme Samples"));
            DirectoryInfo saveDirectory = new DirectoryInfo(Path.Combine(fileDirectory.FullName, @"Engine.Sgml.Test\Saved Docs"));
            fileDirectory = new DirectoryInfo(Path.Combine(fileDirectory.FullName, @"Engine.Sgml.Test\Document Samples"));

            Assert.IsTrue(schemaDirectory.Exists);
            Assert.IsTrue(fileDirectory.Exists);
            Assert.IsTrue(saveDirectory.Exists);

            fileDir = fileDirectory.FullName;
            saveDir = saveDirectory.FullName;
            }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        private string fileDir;
        private string saveDir;
        private SgmlDocument doc;

        private SgmlDocument LoadDocument(string fileName) {
            Uri address = ResolveFileUrl(fileName);
            if (doc == null) {
                //DtdSchema schema = DtdSchema.Load(new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"), "html");
                //DtdSchema schema = DtdSchema.Load(new Uri(@"http://www.w3.org/TR/html4/loose.dtd"), "HTML");
                doc = new SgmlDocument();
                //doc.Settings.ValidatorSettings.ProhibitDtdProcessing = true;
                }
            doc.Load(address);
            return doc;
            }

        private Uri ResolveFileUrl(string fileName) {
            return new Uri(string.Format("file://{0}", Path.Combine(fileDir, fileName)));
            }

        private void SaveDocument(SgmlDocument doc, string fileName) {
            TextWriter textWriter = new StringWriter();
            doc.Save(textWriter);
            File.WriteAllText(Path.Combine(saveDir, fileName), doc.ToString(), Encoding.UTF8);
            }

        public void Main() {
            Uri url = new Uri(@"C:\Documents and Settings\Kir Privalov\Рабочий стол\WCS 2010 03 07\Test\Engine.Sgml.Test\WebPages\");

            SgmlDocument document = new SgmlDocument();
            //document.TraceEnabled = false;
            document.Load(url);

            //int maxLength = document.MaxStackLength;
            string outerSgml = document.ToString();

            XmlReader reader = document.CreateReader();
            bool readed = reader.Read();
            string innerXml = reader.ReadInnerXml();
            string outerXml = reader.ReadOuterXml();

            XPathNavigator navigator = document.CreateNavigator();

            XPathNodeIterator na = navigator.Select(".//a");
            //while (na.MoveNext()) {
            //    Console.WriteLine(na.Current.OuterXml);
            //    Console.WriteLine();
            //    }
            }

        [TestMethod]
        public void ReadEmptyFile() {
            SgmlDocument doc = new SgmlDocument();

            doc.Load(ResolveFileUrl("Empty Example.xml"));

            string content = doc.ToString();
            string xml = doc.ToXml();
            Assert.IsTrue(doc.Root.Nodes.Count == 0);
            Assert.IsTrue(string.IsNullOrWhiteSpace(content));
            Assert.IsTrue(string.IsNullOrWhiteSpace(xml));
            }

        [TestMethod]
        public void LoadDocumentFromTextReader() {
            SgmlDocument document = new SgmlDocument();
            MemoryStream reader = new MemoryStream(File.ReadAllBytes(ResolveFileUrl("HTML Example 001.xml").LocalPath));
            document.Load(reader);
            reader.Dispose();
            }

        [TestMethod]
        public void LoadDocumentFromInternet() {
            SgmlDocument document = new SgmlDocument();
            document.Load(new Uri(@"http://www.homedepot.com/"));
            string content = document.ToString();
            string xml = document.ToXml();
            }

        #region SgmlDocument.Load.Example

        [TestMethod]
        public void LoadDocumentFromInternetGoogle() {
            DtdSchema schema = DtdSchema.Load(new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"), "html");

            SgmlDocument google = new SgmlDocument(schema);
            google.Load(new Uri("http://www.google.com/search?q=Crawling"));

            string html = google.ToString();

            IEnumerable<SElement> links = google.SelectElements("html/body//p/a");
            foreach (SElement anchor in links) {
                Debug.Print(anchor.Attribute("href"));
                }
            }

        #endregion

        [TestMethod]
        public void SaveDocumentToTextWriter() {
            SgmlDocument doc = LoadDocument("HTML Example 001.xml");
            string content = doc.ToString();
            StringWriter writer = new StringWriter();
            doc.Save(writer);

            StringBuilder builder = writer.GetStringBuilder();
            string contentAfterSave = builder.ToString();
            writer.Close();

            Assert.IsTrue(string.Equals(content, contentAfterSave, StringComparison.Ordinal));

            }

        [TestMethod]
        public void SaveDocumentToStream() {
            Uri address = ResolveFileUrl("HTML Example 009.xml");
            SgmlDocument doc = new SgmlDocument();
            doc.Load(address);
            string content = doc.ToString();
            Stream stream = new MemoryStream();
            doc.Save(stream);
            stream.Position = 0;
            string contentAfterSave = null;
            using (StreamReader reader = new StreamReader(stream)) {
                contentAfterSave = reader.ReadToEnd();
                }
            Assert.IsTrue(string.Equals(content, contentAfterSave, StringComparison.Ordinal));

            doc.ValidatorBehavior.PreserveWhitespace = true;
            doc.Load(address);
            content = doc.ToString(true);
            stream = new MemoryStream();
            doc.Save(stream);
            stream.Position = 0;
            contentAfterSave = null;
            using (StreamReader reader = new StreamReader(stream)) {
                contentAfterSave = reader.ReadToEnd();
                }
            Assert.IsTrue(string.Equals(content, contentAfterSave, StringComparison.Ordinal));
            }

        [TestMethod]
        public void AllocateTRelementsTest() {
            SgmlDocument doc = LoadDocument("HTML Example 001.xml");
            string content = doc.ToString();
            string xml = doc.ToXml();
            XPathNavigator navigator = doc.CreateNavigator();
            Assert.IsTrue(3 == navigator.Select(".//FORM/div/table/TBODY/tr").Count);
            SaveDocument(doc, "HTML Example 001.html");
            }

        [TestMethod]
        public void ReadHtmlExample002() {
            SgmlDocument doc = LoadDocument("HTML Example 002.xml");
            string content = doc.ToString();
            XPathNavigator navigator = doc.CreateNavigator();
            Assert.IsTrue(4 == navigator.Select(".//ul[@id = 'availMsg']/li").Count);
            SaveDocument(doc, "HTML Example 002.html");
            }

        [TestMethod]
        public void ReadHtmlExample003() {
            SgmlDocument doc = LoadDocument("HTML Example 003.xml");
            string content = doc.ToString();
            string xml = doc.ToXml();
            XPathNavigator navigator = doc.CreateNavigator();
            Assert.IsTrue(5 == navigator.Select(".//table/TBODY/TR/td").Count);
            Assert.IsTrue(1 == navigator.Select(".//table/TBODY/TR/td/ul/li").Count);
            SaveDocument(doc, "HTML Example 003.html");
            }

        [TestMethod]
        public void ReadHtmlExample004() {
            // <ul>
            // <li> <a> </li>
            // <li> ....
            // </ul>
            SgmlDocument doc = LoadDocument("HTML Example 004.xml");
            string content = doc.ToString();
            XPathNavigator navigator = doc.CreateNavigator();
            SaveDocument(doc, "HTML Example 004.html");

            SElement ul = doc.SelectElement(".//ul");
            Assert.IsNotNull(ul);
            Assert.IsTrue(ul.Elements().Count() == 7);
            IEnumerable<SElement> anchors = ul.SelectElements("a");
            Assert.IsTrue(anchors.Count() == 3);
            foreach (SElement anchor in anchors) {
                Assert.IsTrue(anchor.NextNode.LocalName == "li");
                }
            }

        [TestMethod]
        public void ReadHtmlExample005() {
            SgmlDocument doc = LoadDocument("HTML Example 005.xml");
            string content = doc.ToString();
            SaveDocument(doc, "HTML Example 005.html");
            XPathNavigator navigator = doc.CreateNavigator();
            // Элемент TD может быть не закрытым элементом. Для правильного размещения элементов, несоответствующих модели
            // содержимого, нужно изменить стратегию их размещения в документе (InconsistentBlcoksAllocationStrategy class)
            Assert.IsTrue(5 == navigator.Select(".//form/table/TBODY/tr").Count);
            }

        [TestMethod]
        public void ReadHtmlExample006() {
            SgmlDocument doc = LoadDocument("HTML Example 006.xml");
            string content = doc.ToString();
            string xml = doc.ToXml();
            XPathNavigator navigator = doc.CreateNavigator();
            Assert.IsNotNull(navigator.SelectSingleNode(".//div[@id = 'main']"));
            SaveDocument(doc, "HTML Example 006.html");
            }

        [TestMethod]
        public void ReadHtmlExample007() {
            // </body>
            // </html>
            // <div> ....
            SgmlDocument doc = LoadDocument("HTML Example 007.xml");
            string content = doc.ToString();
            XPathNavigator navigator = doc.CreateNavigator();
            Assert.IsNotNull(navigator.SelectSingleNode(".//div[@id = 'main']"));
            SaveDocument(doc, "HTML Example 007.html");
            }

        [TestMethod]
        public void ReadHtmlExample008() {
            SgmlDocument doc = LoadDocument("HTML Example 008.xml");
            SaveDocument(doc, "HTML Example 008.html");
            string content = doc.ToString();
            XPathNavigator navigator = doc.CreateNavigator();
            Assert.IsTrue(8 == navigator.Select(".//div[@id = 'famRCol']/div[position() > 2 and position() != last()]").Count);
            }

        [TestMethod]
        public void ReadHtmlExample009() {
            // </a&nbsp;&nbsp;<tr>
            SgmlDocument doc = LoadDocument("HTML Example 009.xml");
            SaveDocument(doc, "HTML Example 009.html");
            string content = doc.ToString();
            string xml = doc.ToXml();
            XPathNavigator navigator = doc.CreateNavigator();
            XPathNavigator element = navigator.SelectSingleNode(".//form[@name = 'itemList']/table/TBODY/tr[3]/td/table/TBODY");
            if (element == null)
                element = navigator.SelectSingleNode(".//form[@name = 'itemList']/table/tr[3]/td/table");
            Assert.IsNotNull(element);
            Assert.IsTrue(/*64*/62 == element.Select("tr").Count);
            }

        [TestMethod]
        public void ReadHtmlExample010() {
            // <b><u> ... </b></u><ul> 
            SgmlDocument doc = LoadDocument("HTML Example 010.xml");
            SaveDocument(doc, "HTML Example 010.html");
            string content = doc.ToString();
            XPathNavigator navigator = doc.CreateNavigator();
            SElement div = navigator.SelectSingleNode(".//div[@class = 'item-caption']").UnderlyingObject as SElement;
            Assert.IsTrue(3 == navigator.Select(".//div[@class = 'item-caption']/b").Count);
            }

        [TestMethod]
        public void ReadHtmlExample011() {
            // <table>
            //    <tr>
            //      <td>
            //        <div class="ProdDesc BodyS">
            //          <shorttext>
            //            <br/>
            //            <br/>
            //            <b>Features</b>
            //            <ul>
            //              <li>4-in-1 Technology
            //              <li>Multi-Color VFD Display
            //              <li>No Water Tank &hellip;
            //        </div>
            //      </td>
            //    </tr>
            // </table>
            SgmlDocument doc = LoadDocument("HTML Example 011.xml");
            SaveDocument(doc, "HTML Example 011.html");
            string content = doc.ToString();
            string xml = doc.ToXml();
            XPathNavigator navigator = doc.CreateNavigator();
            Assert.IsTrue(46 == navigator.Select(".//div[@id = 'shelfDiv']/div[@id = 'border']/div[@class = 'item' or @class = 'item firstRow']").Count);
            }

        [TestMethod]
        public void ReadHtmlExample012() {
            // </li>
            // <span id="itemS2SEDDM" style="display: none;">
            // <p id="s2se_DDM_0"></p>
            // </span>
            // </ul>
            SgmlDocument doc = LoadDocument("HTML Example 012.xml");
            string content = doc.ToString();
            XPathNavigator navigator = doc.CreateNavigator();
            string outerXml = navigator.OuterXml;
            Assert.IsTrue(2 == navigator.Select(".//BODY/ul").Count);
            Assert.IsTrue(2 == doc.SelectElements(".//BODY/ul").Count());
            SaveDocument(doc, "HTML Example 012.html");
            }

        [TestMethod]
        public void ReadHtmlExample013() {
            // </body>
            //</html>
            // .......
            //<div id="main">
            SgmlDocument doc = LoadDocument("HTML Example 013.xml");

            string content = doc.ToString();
            XPathNavigator navigator = doc.CreateNavigator();
            XPathNavigator div = navigator.SelectSingleNode(".//div[@id = 'main']");
            Assert.IsNotNull(div);
            SaveDocument(doc, "HTML Example 013.html");
            }

        [TestMethod]
        public void ReadHtmlExample014() {
            // <li class="inShip intShipHide">
            //  <span class="icon"></span>In Stock and Available for Ground Shipping.
            // </li>
            // <div id="LMPGetItNow" style="display: none"> </div>
            // <li class="intShip" style="display: none">
            SgmlDocument doc = LoadDocument("HTML Example 014.xml");
            string content = doc.ToString();
            XPathNavigator navigator = doc.CreateNavigator();
            Assert.IsNotNull(navigator.SelectSingleNode(".//ul[@id = 'availMsg']/li[@class = 'unvIntShip']"));
            SaveDocument(doc, "HTML Example 014.html");
            }

        [TestMethod]
        public void ReadHtmlExample015() {
            // <ul hotness="{actions:[{Wizzle:'dropNav'}]}">
            // <li id="mainNav1">
            // <a href="/category/index.jsp?categoryId=2568444" onClick="window.location.href='/category/index.jsp?categoryId=2568444&clickid=topnav_lawn';return false;">
            //   <div class="hidMe">Lawn & Garden</div>
            // </a>
            // <!--PMO 437313::handling clickid through javascript-->
            // <ul>
            SgmlDocument doc = LoadDocument("HTML Example 015.xml");
            string content = doc.ToString();
            Assert.IsNotNull(doc.SelectElement(".//*[@id = 'topnav']/div/ul/li/ul"));
            SaveDocument(doc, "HTML Example 015.html");
            }

        [TestMethod]
        public void ReadHtmlExample016() {
            //<tr>
            //  <th class="rTime">
            //      <a href="/horses2/cards/card.sd?race_id=499161&amp;r_date=2010-03-06" title="Click to view card: sportingbet.com Handicap Hurdle Cl23m&frac12;f (3m110y) 4yo+">2:20</a>
            //  </th>
            //  <td>
            //      <a href="/horses2/cards/card.sd?race_id=499161&amp;r_date=2010-03-06" title="Click to view card: sportingbet.com Handicap Hurdle Cl23m&frac12;f (3m110y) 4yo+">sportingbet.com Handicap Hurdle Cl2 3m110y</a>
            //      <b>CH4
            //      <b>
            //      </td>
            SgmlDocument doc = LoadDocument("HTML Example 016.xml");
            XPathNavigator navigator = doc.CreateNavigator();
            string content = doc.ToString();
            string xmlContent = doc.ToXml();
            Assert.IsNotNull(doc.SelectElement(".//table[@class = 'cardsGrid']/TBODY/tr/*/b/b"));
            SaveDocument(doc, "HTML Example 016.html");
            }

        [TestMethod]
        public void ReadHtmlExample017() {
            SgmlDocument doc = LoadDocument("HTML Example 017.xml");
            XPathNavigator navigator = doc.CreateNavigator();
            string content = doc.ToString();
            string xmlContent = doc.ToXml();
            SaveDocument(doc, "HTML Example 017.html");
            }

        [TestMethod]
        public void ReadHtmlExample018() {
            SgmlDocument doc = LoadDocument("HTML Example 018.xml");
            XPathNavigator navigator = doc.CreateNavigator();
            string content = doc.ToString();
            string xmlContent = doc.ToXml();
            SaveDocument(doc, "HTML Example 018.html");
            }

        [TestMethod]
        public void ReadHtmlExample019() {
            SgmlDocument doc = LoadDocument("HTML Example 019.xml");
            XPathNavigator navigator = doc.CreateNavigator();
            string content = doc.ToString();
            string xmlContent = doc.ToXml();
            SaveDocument(doc, "HTML Example 019.html");
            }

        [TestMethod]
        public void ReadHtmlExample020() {
            SgmlDocument doc = LoadDocument("HTML Example 020.xml");
            XPathNavigator navigator = doc.CreateNavigator();
            string content = doc.ToString();
            string xmlContent = doc.ToXml();
            SaveDocument(doc, "HTML Example 020.html");
            }

        [TestMethod]
        public void ReadHtmlExample021() {
            SgmlDocument doc = LoadDocument("HTML Example 021.xml");
            XPathNavigator navigator = doc.CreateNavigator();
            string content = doc.ToString();
            string xmlContent = doc.ToXml();
            SaveDocument(doc, "HTML Example 021.html");
            }

        [TestMethod]
        public void AppendToExistingBlocksTest() {
            SgmlDocument doc = LoadDocument("AppendToExistingBlocks (Infinity Loop Error).xml");
            XPathNavigator navigator = doc.CreateNavigator();
            string content = doc.ToString();
            string xmlContent = doc.ToXml();
            SaveDocument(doc, "AppendToExistingBlocks (Infinity Loop Error).html");
            }

        [TestMethod]
        public void ReadXmlExample001() {
            SgmlDocument doc = LoadDocument("XML Example 001.xml");
            string content = doc.ToString();
            string xml = doc.ToXml();
            Assert.IsFalse(string.IsNullOrWhiteSpace(content));
            Assert.IsFalse(string.IsNullOrWhiteSpace(xml));
            }

        [TestMethod]
        public void ReadXmlExample002() {
            SgmlDocument doc = LoadDocument("XML Example 002.xml");
            Assert.IsTrue(doc.Root.Elements().Count() == 3);
            Assert.IsTrue(doc.Root.LastNode.LocalName == "html");
            string content = doc.ToString();

            string xml = doc.ToXml();
            Assert.IsFalse(string.IsNullOrWhiteSpace(content));
            Assert.IsFalse(string.IsNullOrWhiteSpace(xml));
            }

        [TestMethod]
        public void ReadXmlExample003() {
            SgmlDocument doc = LoadDocument("XML Example 003.xml");
            string content = doc.ToString();

            Assert.IsTrue(doc.Root.Elements().Count() == 3);
            Assert.IsTrue(doc.Root.FirstNode.NodeType == SgmlNodeType.ProcessingInstruction);
            Assert.IsTrue(doc.Root.LastNode.LocalName == "root");
            string xml = doc.ToXml();
            Assert.IsFalse(string.IsNullOrWhiteSpace(content));
            Assert.IsFalse(string.IsNullOrWhiteSpace(xml));
            }

        [TestMethod]
        public void ReadXmlExample004() {
            SgmlDocument doc = LoadDocument("XML Example 004.xml");
            string content = doc.ToString();
            }
        }
    }
